package com.tc.quartz.frame.common;

import org.quartz.JobDataMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

/**
 * 扩展spring BeanUtils对象
 * @author yongjin.ye
 *
 */
public abstract class ObjectUtil extends org.springframework.beans.BeanUtils{
	
	protected  static Logger log = LoggerFactory.getLogger(ObjectUtil.class);
	
	/**
	 * 扩展属性拷贝方法,数组为需要拷贝的参数
	 * @see BeanWrapper
	 * @param source 要拷贝的对象
	 * @param target 拷贝到此目标
	 * @param needProperties 需要拷贝的字段
	 * @throws BeansException
	 */
	public static void copyByName(Object source, Object target, String ... needProperties) throws BeansException {
		copyByName(source, target, null, needProperties);
	}
	
	/**
	 * 扩展属性拷贝方法,数组为需要拷贝的参数
	 * @see BeanWrapper
	 */
	private static void copyByName(Object source, Object target, Class<?> editable, String ... needProperties)
			throws BeansException {
		
		
		Assert.notNull(needProperties, "不允许 更新!");	//needProperties must not be null
		Assert.notNull(source, "参数不能为空");	//Source must not be null
		Assert.notNull(target, "没有查询到要更新的数据[copyProperties]");	//Target must not be null

		Class<?> actualEditable = target.getClass();
		if (editable != null) {
			if (!editable.isInstance(target)) {
				throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
						"] not assignable to Editable class [" + editable.getName() + "]");
			}
			actualEditable = editable;
		}
		PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
		List<String> needList = (needProperties != null) ? Arrays.asList(needProperties) : null;

		for (PropertyDescriptor targetPd : targetPds) {
			if (targetPd.getWriteMethod() != null && needProperties != null && needList!=null &&needList.contains(targetPd.getName())) {
				PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
				if (sourcePd != null && sourcePd.getReadMethod() != null) {
					try {
						Method readMethod = sourcePd.getReadMethod();
						if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
							readMethod.setAccessible(true);
						}
						Object value = readMethod.invoke(source);
						Method writeMethod = targetPd.getWriteMethod();
						if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
							writeMethod.setAccessible(true);
						}
						writeMethod.invoke(target, value);
					}
					catch (Throwable ex) {
						throw new FatalBeanException("Could not copy properties from source to target", ex);
					}
				}
			}
		}
	}


	/**
	 * 将数据库中jobData(byte)数据转换为map
	 * @param jobData
	 * @return
	 */
	public static JobDataMap formatJobData2Map(byte[] jobData){
		if (null != jobData && jobData.length > 0) {
			InputStream inStream = new ByteArrayInputStream(jobData);
			Properties properties = new Properties();
			try {
				properties.load(inStream);
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					inStream.close();
				} catch (Exception e) {
					log.error("转换JobDateMap异常：", e);
				}
			}
			return new JobDataMap(properties);
		}
		return null;
	}

	
}
